package bg.tu.varna.pms.client;

import java.awt.EventQueue;
import java.util.ArrayList;
import org.omg.CORBA.portable.ApplicationException;
import bg.tu.varna.pms.client.controller.ApplicationEvent;
import bg.tu.varna.pms.model.communication.LoginMessage;

/**
 * ApplicationContext is singleton class that provide application specific operations for the GUI.
 * Those operations are login, logout and register.
 * Instance of the context is accessible through ApplicationContext.getApplicationContext().
 * @author Gospodin Gospodinov
 */
public class ApplicationContext {
	private static ApplicationContext mApplicationContext = new ApplicationContext();
	private UserContext mUserContext;
	private final ArrayList<ApplicationEvent> mEventListeners = new ArrayList<>( 1 );

	private ApplicationContext() {}

	public static ApplicationContext getApplicationContext() {
		return mApplicationContext;
	}

	public void addApplicationEventListener( ApplicationEvent listener ) {
		mEventListeners.add( listener );
	}
	public void removeApplicationEventListener( ApplicationEvent listener ) {
		mEventListeners.remove( listener );
	}

	public UserContext getUserContext() {
		return mUserContext;
	}

	public void login( final String username, final char[] password, int a ) {
		if ( mUserContext == null ) {
			EventQueue.invokeLater( new Runnable() {
				@Override
				public void run() {
					LoginMessage.Response vResponse;
					try {
						vResponse = ServerReference.getInstance().login( username, password );
						if ( vResponse.getSuccess() ) {
							mUserContext = new UserContext( vResponse );
						}
						for ( ApplicationEvent vListener : mEventListeners ) {
							vListener.loginComplete( vResponse.getSuccess() );
						}
					} catch ( ApplicationException e ) {
						e.printStackTrace( System.err );
						for ( ApplicationEvent vListener : mEventListeners ) {
							vListener.loginError( e );
						}
					}
				}
			} );
		} else {
			EventQueue.invokeLater( new Runnable() {
				@Override
				public void run() {
					ApplicationException vEx = new ApplicationException( "User already logged in", null );
					for ( ApplicationEvent vListener : mEventListeners ) {
						vListener.loginError( vEx );
					}
				}
			} );
		}
	}
	public void logout() {
		if ( mUserContext != null ) {
			EventQueue.invokeLater( new Runnable() {
				@Override
				public void run() {
					try {
						if ( ServerReference.getInstance().logout( mUserContext.getSessionID(), mUserContext.getUsername() ) ) {
							mUserContext = null;
							for ( ApplicationEvent vListener : mEventListeners ) {
								vListener.logoutComplete( true );
							}
						} else {
							for ( ApplicationEvent vListener : mEventListeners ) {
								vListener.logoutComplete( false );
							}
						}
					} catch ( ApplicationException e ) {
						e.printStackTrace( System.err );
						for ( ApplicationEvent vListener : mEventListeners ) {
							vListener.logoutError( e );
						}
					}
				}
			} );
		} else {
			EventQueue.invokeLater( new Runnable() {
				@Override
				public void run() {
					ApplicationException vEx = new ApplicationException( "No user to logout", null );
					for ( ApplicationEvent vListener : mEventListeners ) {
						vListener.logoutError( vEx );
					}
				}
			} );
		}
	}
	public void register( final String username, final char[] password ) {
		EventQueue.invokeLater( new Runnable() {
			@Override
			public void run() {
				try {
					if ( ServerReference.getInstance().register( username, password ) ) {
						for ( ApplicationEvent vListener : mEventListeners ) {
							vListener.registrationComplete( true );
						}
					} else {
						for ( ApplicationEvent vListener : mEventListeners ) {
							vListener.registrationComplete( false );
						}
					}
				} catch ( ApplicationException e ) {
					e.printStackTrace( System.err );
					for ( ApplicationEvent vListener : mEventListeners ) {
						vListener.registrationError( e );
					}
				}
			}
		} );
	}
}
